﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using InkFx.WinControl.Core;
using InkFx.WinControl.Utils;
using Temp_20190910_AForm8.Dock;
using DTGS = InkFx.WinControl.XIDETabGroupState;

namespace InkFx.WinControl
{
    public partial class XIDETipForm : System.Windows.Forms.Form
    {
        public XIDETipForm(XIDEPanel idePanel, System.Windows.Forms.Control ctrl, XIDEFloatForm floatForm)
        {
            InitializeComponent();
            //base.DoubleBuffered = true; //这种需要快速弹出的窗体, 设置 双缓冲 只会减慢启动速度
            base.ShowInTaskbar = false;
            //base.BackColor = Color.BlueViolet;


            this.Control = ctrl;
            this.IDEPanel = idePanel;
            this.TabGroup = floatForm.TabGroup;

            m_FloatForm = floatForm;
            m_FloatForm.FormClosed += FloatForm_FormClosed;

            if (Control != null)
            {
                Control.LocationChanged += ControlRectChanged;
                Control.SizeChanged += ControlRectChanged;
            }
        }



        public static XIDETipForm ShowTipForm(XIDEPanel idePanel, System.Windows.Forms.Control ctrl, XIDEFloatForm floatForm)
        {
            var group = floatForm == null ? null : floatForm.TabGroup;
            if (group == null) return null;

            var rect = Win32API.GetWindowRectangle(ctrl.Handle);
            var parent = idePanel.FindForm();
            XIDETipForm form = new XIDETipForm(idePanel, ctrl, floatForm);
            form.TopMost = true;
            form.Bounds = rect;
            form.Show(parent);
            //form.Owner = parent;
            //Win32API.ShowWindow(form.Handle, 4);

            return form;
        }


        protected XIDELayoutInfo m_TipLayout = null;
        protected List<XIDEAreaInfo> m_ListTipArea = new List<XIDEAreaInfo>();


        private void ControlRectChanged(object sender, EventArgs e)
        {
            ResetRect();
        }

        public void ResetRect()
        {
            var ctrl = Control;
            if (ctrl == null) return;

            var rect = Win32API.GetWindowRectangle(ctrl.Handle);
            this.Bounds = rect;

            #region  计算 附着区域

            m_ListTipArea.Clear();
            if (ctrl is XIDEPanel)
            {
                #region  IDEPanel 四周的附着区域

                var ctrl1 = (XIDEPanel)ctrl;
                const int OFFSET = 10;
                const int SIZE = 32;
                int width = this.Width;
                int height = this.Height;
                Rectangle rectT = new Rectangle((width - SIZE) / 2, OFFSET, SIZE, SIZE);
                Rectangle rectB = new Rectangle((width - SIZE) / 2, height - SIZE - OFFSET, SIZE, SIZE);
                Rectangle rectL = new Rectangle(OFFSET, (height - SIZE) / 2, SIZE, SIZE);
                Rectangle rectR = new Rectangle(width - SIZE - OFFSET, (height - SIZE) / 2, SIZE, SIZE);


                var areaT = new XIDEAreaInfo(XIDEAlignment.Top, ctrl1) { Rect = rectT };
                var areaB = new XIDEAreaInfo(XIDEAlignment.Bottom, ctrl1) { Rect = rectB };
                var areaL = new XIDEAreaInfo(XIDEAlignment.Left, ctrl1) { Rect = rectL };
                var areaR = new XIDEAreaInfo(XIDEAlignment.Right, ctrl1) { Rect = rectR };
                m_ListTipArea.AddRange(new[] { areaT, areaB, areaL, areaR });

                #endregion
            }
            else if (ctrl is XIDEPanelCenter)
            {
                #region  主文档 中央的附着区域

                var ctrl2 = (XIDEPanelCenter)ctrl;
                if (ctrl2.Controls.Count <= 0)
                {
                    const int SIZE = 32;
                    int width = ctrl2.Width;
                    int height = ctrl2.Height;
                    Rectangle rectC = new Rectangle((width - SIZE) / 2, (height - SIZE) / 2, SIZE, SIZE);

                    var areaC = new XIDEAreaInfo(XIDEAlignment.Center, ctrl2.IDEPanel) { Rect = rectC };
                    m_ListTipArea.Add(areaC);
                }

                #endregion
            }
            else if (ctrl is XIDETabGroup)
            {
                #region  Group 的拆分附着区域

                var ctrl3 = (XIDETabGroup)ctrl;
                bool hide = (ctrl3 == this.TabGroup) || (ctrl3.State != DTGS.Expand && ctrl3.State != DTGS.Float && ctrl3.State != DTGS.Popup);

                if (hide) { m_TipLayout = null; }
                else
                {
                    m_TipLayout = new XIDELayoutInfo(XIDELayoutEnum.TabGroup, (XIDETabGroup)ctrl);
                    m_TipLayout.Rect = new Rectangle(Point.Empty, this.Size);
                    //Console.WriteLine(m_TipLayout.TipRect);
                }

                #endregion
            }

            #endregion

            #region  计算Region

            var oldRegion = this.Region;
            var newRegion = new Region(Rectangle.Empty);

            if (m_TipLayout != null && m_TipLayout.TabGroup != null)
            {
                newRegion.Union(m_TipLayout.TipRect.RectCenter);
                newRegion.Union(m_TipLayout.TipRect.RectLeft);
                newRegion.Union(m_TipLayout.TipRect.RectRight);
                newRegion.Union(m_TipLayout.TipRect.RectTop);
                newRegion.Union(m_TipLayout.TipRect.RectBottom);
            }
            else if (m_ListTipArea != null && m_ListTipArea.Count >= 1)
            {
                foreach (var area in m_ListTipArea)
                    newRegion.Union(area.Rect);
            }

            //this.Region = new Region(new Rectangle(0, 0, 100, 100));
            this.Region = newRegion;
            if (oldRegion != null) oldRegion.Dispose();


            #endregion

        }


        private XIDEFloatForm m_FloatForm = null;
        public System.Windows.Forms.Control Control { get; private set; }
        public XIDEPanel IDEPanel { get; private set; }
        public XIDETabGroup TabGroup { get; private set; }



        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            ResetRect();
        }
        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            base.DoubleBuffered = true;
        }
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            if (Control != null)
            {
                Control.LocationChanged -= ControlRectChanged;
                Control.SizeChanged -= ControlRectChanged;
            }
            IDEPanel = null;
            Control = null;
        }
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            this.Refresh();
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            var g = e.Graphics;
            var ctrl = this.Control;
            if (ctrl == null || !ctrl.IsHandleCreated || ctrl.Disposing || ctrl.IsDisposed) return;


            //不再将所有提示区域 显示在同一个窗体上

            if (m_TipLayout != null && m_TipLayout.TabGroup != null)
                DrawIDETabGroup(g, m_TipLayout);

            if (m_ListTipArea != null && m_ListTipArea.Count >= 1)
                foreach (var area in m_ListTipArea)
                {
                    var align = area.Align;
                    if (align != XIDEAlignment.Top && align != XIDEAlignment.Bottom && align != XIDEAlignment.Left && align != XIDEAlignment.Right && align != XIDEAlignment.Center) continue;
                    DrawIDEAlign(g, area);
                }
        }

        public virtual void DrawIDETabGroup(Graphics g, XIDELayoutInfo layout)
        {
            Image back = layout.TipRect.OnlyCenter ? XIDEPanelResource.未命名_10 : XIDEPanelResource.未命名_9;
            g.DrawImage(back, layout.TipRect.RectFull);

            const bool debug = false;


            if (debug)
            {
                #region  DEBUG 重绘模式

                Color colorC = Color.FromArgb(200, Color.Coral);
                Color colorT = Color.FromArgb(200, Color.IndianRed);
                Color colorB = Color.FromArgb(200, Color.IndianRed);
                Color colorL = Color.FromArgb(200, Color.CornflowerBlue);
                Color colorR = Color.FromArgb(200, Color.CornflowerBlue);

                var align = layout.MouseInTipRect();
                if (align == XIDEAlignment.Center) colorC = Color.FromArgb(255, colorC);
                if (align == XIDEAlignment.Top) colorT = Color.FromArgb(255, colorT);
                if (align == XIDEAlignment.Bottom) colorB = Color.FromArgb(255, colorB);
                if (align == XIDEAlignment.Left) colorL = Color.FromArgb(255, colorL);
                if (align == XIDEAlignment.Right) colorR = Color.FromArgb(255, colorR);

                g.FillRectangle(new SolidBrush(colorC), layout.TipRect.RectCenter);


                g.FillRectangle(new SolidBrush(colorT), layout.TipRect.RectTop);
                g.FillRectangle(new SolidBrush(colorB), layout.TipRect.RectBottom);
                g.FillRectangle(new SolidBrush(colorL), layout.TipRect.RectLeft);
                g.FillRectangle(new SolidBrush(colorR), layout.TipRect.RectRight);

                #endregion
            }
            else
            {
                #region  正式重绘

                var align = layout.MouseInTipRect();
                Image imgC = GetTipImage(XIDEAlignment.Center, (align == XIDEAlignment.Center || align == XIDEAlignment.FloatCenter));
                Image imgT = GetTipImage(XIDEAlignment.Top, align == XIDEAlignment.Top);
                Image imgB = GetTipImage(XIDEAlignment.Bottom, align == XIDEAlignment.Bottom);
                Image imgL = GetTipImage(XIDEAlignment.Left, align == XIDEAlignment.Left);
                Image imgR = GetTipImage(XIDEAlignment.Right, align == XIDEAlignment.Right);

                g.DrawImage(imgC, layout.TipRect.RectCenter);
                g.DrawImage(imgT, layout.TipRect.RectTop);
                g.DrawImage(imgB, layout.TipRect.RectBottom);
                g.DrawImage(imgL, layout.TipRect.RectLeft);
                g.DrawImage(imgR, layout.TipRect.RectRight);

                #endregion
            }
        }
        public virtual void DrawIDEAlign(Graphics g, XIDEAreaInfo area)
        {
            Image back = XIDEPanelResource.未命名_3;
            Rectangle rect1 = area.Rect;
            Rectangle rect2 = new Rectangle(rect1.X - (back.Width - rect1.Width) / 2, rect1.Y - (back.Height - rect1.Height) / 2, back.Width, back.Height);
            g.DrawImage(back, rect2);


            const bool debug = false;
            if (debug)
            {
                #region  DEBUG 重绘模式

                Color colorT = Color.FromArgb(200, Color.IndianRed);
                Color colorB = Color.FromArgb(200, Color.IndianRed);
                Color colorL = Color.FromArgb(200, Color.CornflowerBlue);
                Color colorR = Color.FromArgb(200, Color.CornflowerBlue);
                Color colorC = Color.FromArgb(200, Color.DarkCyan);

                var align = area.MouseInTipRect();
                if (align == XIDEAlignment.Top) colorT = Color.FromArgb(255, colorT);
                if (align == XIDEAlignment.Bottom) colorB = Color.FromArgb(255, colorB);
                if (align == XIDEAlignment.Left) colorL = Color.FromArgb(255, colorL);
                if (align == XIDEAlignment.Right) colorR = Color.FromArgb(255, colorR);
                if (align == XIDEAlignment.Center) colorR = Color.FromArgb(255, colorR);

                if (area.Align == XIDEAlignment.Top) g.FillRectangle(new SolidBrush(colorT), area.Rect);
                if (area.Align == XIDEAlignment.Bottom) g.FillRectangle(new SolidBrush(colorB), area.Rect);
                if (area.Align == XIDEAlignment.Left) g.FillRectangle(new SolidBrush(colorL), area.Rect);
                if (area.Align == XIDEAlignment.Right) g.FillRectangle(new SolidBrush(colorR), area.Rect);
                if (area.Align == XIDEAlignment.Center) g.FillRectangle(new SolidBrush(colorC), area.Rect);

                #endregion
            }
            else
            {
                #region  正式重绘

                var align = area.MouseInTipRect();
                Image imgC = GetTipImage(XIDEAlignment.Center, (align == XIDEAlignment.Center || align == XIDEAlignment.FloatCenter));
                Image imgT = GetTipImage(XIDEAlignment.Top, align == XIDEAlignment.Top);
                Image imgB = GetTipImage(XIDEAlignment.Bottom, align == XIDEAlignment.Bottom);
                Image imgL = GetTipImage(XIDEAlignment.Left, align == XIDEAlignment.Left);
                Image imgR = GetTipImage(XIDEAlignment.Right, align == XIDEAlignment.Right);

                if (area.Align == XIDEAlignment.Center || align == XIDEAlignment.FloatCenter) g.DrawImage(imgC, area.Rect);
                if (area.Align == XIDEAlignment.Top) g.DrawImage(imgT, area.Rect);
                if (area.Align == XIDEAlignment.Bottom) g.DrawImage(imgB, area.Rect);
                if (area.Align == XIDEAlignment.Left) g.DrawImage(imgL, area.Rect);
                if (area.Align == XIDEAlignment.Right) g.DrawImage(imgR, area.Rect);

                #endregion
            }
        }


        private bool m_InvalidateTipRect = false;
        public new void Invalidate()
        {
            if (m_TipLayout != null && m_TipLayout.MouseInRect())
            {
                var align = m_TipLayout.MouseInTipRect();
                if (align != XIDEAlignment.None) { base.Invalidate(m_TipLayout.TipRect.RectFull); m_InvalidateTipRect = true; return; }
            }

            if (m_ListTipArea != null && m_ListTipArea.Count >= 1)
            {
                foreach (var area in m_ListTipArea) { if (area.MouseInRect()) { base.Invalidate(area.Rect); m_InvalidateTipRect = true; return; } } 
            }

            if (m_InvalidateTipRect) { base.Invalidate(); m_InvalidateTipRect = false; }
        }


        public XIDEEventArgs NewIDEEventArgs()
        {
            var layout = m_TipLayout;
            var dockAreas = m_ListTipArea;

            if (layout != null)
            {
                var align = layout.MouseInTipRect();
                if (align != XIDEAlignment.None)
                {
                    //MessageBox.Show("tabGroup");
                    return new XIDEEventArgs { Control = layout.TabGroup, TipLayout = layout, Alignment = align };
                }
            }

            if (dockAreas != null)
                foreach (var area in dockAreas)
                {
                    var align = area.MouseInTipRect();
                    if (align != XIDEAlignment.None)
                    {
                        //MessageBox.Show("tabGroup");
                        return new XIDEEventArgs { Control = null, TipArea = area, Alignment = area.Align };
                    }
                }

            return null;
        }

        private void FloatForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            m_FloatForm.FormClosed -= FloatForm_FormClosed;
            m_FloatForm = null;
            this.Dispose();
        }


        public Image GetTipImage(XIDEAlignment align, bool hover)
        {
            if (align == XIDEAlignment.None) return null;

            int index = 0;
            if (align == XIDEAlignment.Center || align == XIDEAlignment.FloatCenter) index = 0;
            else if (align == XIDEAlignment.Top) index = 1;
            else if (align == XIDEAlignment.Bottom) index = 2;
            else if (align == XIDEAlignment.Left) index = 3;
            else if (align == XIDEAlignment.Right) index = 4;
            int index2 = index * 2 + (hover ? 1 : 0);
            return GetTipImage(index2);
        }


        private static Color m_TitleColor = Color.LightSteelBlue;
        private static Color m_FocusColor = Color.LightYellow;

        private static byte[][] m_ImageCache = new byte[10][];
        private static Image GetTipImage(int index)
        {
            var bytes = m_ImageCache[index];
            if (bytes != null && bytes.Length >= 1) return ImageHelper.GetImageFromBytes(bytes);


            const int SIZE = 32;



            Rectangle[] array = new Rectangle[]
            {
                new Rectangle(5, 7, 22, 20),
                new Rectangle(5, 39, 22, 20),
                new Rectangle(5, 7 + 64, 22, 8),
                new Rectangle(5, 39 + 64, 22, 8),
                new Rectangle(5, 19 + 128, 22, 8),
                new Rectangle(5, 51 + 128, 22, 8),
                new Rectangle(5, 7 + 192, 10, 20),
                new Rectangle(5, 39 + 192, 10, 20),
                new Rectangle(17, 7 + 256, 10, 20),
                new Rectangle(17, 39 + 256, 10, 20),
            };


            Color m_FocusColor2 = ColorHelper.DarkDark(m_FocusColor);
            Color m_TitleColor2 = ColorHelper.DarkDark(m_TitleColor);

            Image btnV10 = XIDEPanelResource.未命名_30;


            using (Bitmap bitmap = new Bitmap(SIZE, SIZE*10))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    using (var brush1 = new SolidBrush(m_FocusColor))
                    using (var brush2 = new SolidBrush(m_FocusColor2))
                    {
                        for (int i = 0; i < 10; i++)
                        {
                            Rectangle rect = new Rectangle(0, SIZE * i, SIZE, SIZE);
                            if (i % 2 == 0) { g.FillRectangle(brush1, rect); }
                            else { g.FillRectangle(brush2, rect); }
                        }
                    }

                    foreach (var rect in array) g.ExcludeClip(rect);

                    using (var brush1 = new SolidBrush(m_TitleColor))
                    using (var brush2 = new SolidBrush(m_TitleColor2))
                    {
                        for (int i = 0; i < 10; i++)
                        {
                            Rectangle rect = new Rectangle(0, SIZE * i, SIZE, SIZE);
                            if (i % 2 == 0) { g.FillRectangle(brush1, rect); }
                            else { g.FillRectangle(brush2, rect); }
                        }
                    }

                    g.ResetClip();
                    g.DrawImage(btnV10, new Rectangle(Point.Empty, bitmap.Size), new Rectangle(Point.Empty, btnV10.Size), GraphicsUnit.Pixel);
                }

                //Directory.CreateDirectory(@"D:\CCC\");
                //bitmap.Save(string.Format(@"D:\CCC\{0:yyyyMMdd_HHmmss_fff}.png", DateTime.Now), ImageFormat.Png);

                Image result = null;
                for (int i = 0; i < 10; i++)
                {
                    Image img = GetTipImage(bitmap, i);
                    m_ImageCache[i] = ImageHelper.GetImageBytes(img);
                    if (index == i) result = img;
                }
                return result;
            }

        }
        private static Image GetTipImage(Image imgV10, int index)
        {
            const int SIZE = 32;
            Bitmap bitmap = new Bitmap(SIZE, SIZE);
            using (Graphics g = Graphics.FromImage(bitmap))
                g.DrawImage(imgV10, new Rectangle(0, 0, SIZE, SIZE), new Rectangle(0, (index * SIZE), SIZE, SIZE), GraphicsUnit.Pixel);
            return bitmap;
        }


        public virtual new void Dispose()
        {
            Control = null;
            TabGroup = null;
            IDEPanel = null;

            if (!this.Disposing && !this.IsDisposed) { this.Close(); base.Dispose(); }
        }
    }
}
